---------------------------------------------------------------
-- @Copyright：           zour
-- @Description：         各数据库接口

-- @modify time           2021-09-27
---------------------------------------------------------------
require "modules.business_advert.advert_define"

local FOO = {
    _VERSION    = '0.1.0',
	KEYS = {
		NONE				= 0,
		INVALID				= 1,
	},

	advert_ssdb_dc_client = nil, 	--ssdb_dc 连接管理
}

--===================================logic function=====================================
FOO.init = function ()
	--ngx.ctx.xff = biz_utils.real_client_ip() or "nil"
	--ssdb_dc
    if (not FOO.advert_ssdb_dc_client) and ns_config.advert_ssdb_server_dc then
        log.debug( "create advert_ssdb_dc_client [new ns_ssdbDcClient]" )
		FOO.advert_ssdb_dc_client = ns_ssdbDcClient:new(ADVERT,
		ns_config.advert_ssdb_server_dc.server,
		ns_config.advert_ssdb_server_dc.select)
    end
end

FOO.final = function ()
	--防止无限循环,只调一次
	if ngx.ctx.gg_final_has_called then
		return
	end

	ngx.ctx.gg_final_has_called = true

	--归还ssdb dc socket连接到连接池
	if  FOO.advert_ssdb_dc_client then
		FOO.advert_ssdb_dc_client:final();
	end
end

--异常退出
FOO.error_exit = function( txt )
    FOO.final()
    log.error(txt);
    ns_time.print_cost_all();
    ngx.exit(0);
end

--按格式返回 lua table or json
FOO.return_table = function( tmp_t, data )
	local t = {}
	if  tmp_t and type(tmp_t)~='table' then
		t.ret=tmp_t
	else 
		for k, v in pairs(tmp_t) do
			t[k] = v
		end
		t.data = data
	end

	if  ngx.ctx.m_params.json == '1' then
		--json ajax 跨域
		ngx.header["Access-Control-Allow-Origin"] = "*";
		ngx.header["Server"] = "php";

		log.debug("return json");
		local jret = uu.table2json( t );
		ngx.say(jret);

	elseif ngx.ctx.m_params.log == '1' then
		--log
		log.debug( "<br><br>=========================return begin========" );
		uu.var_dump(t)
		log.debug( "=========================return end========<br><br>" );

	else
		--lua
		local ret = table.tostring( t );
		--ngx.header["Content-Length"] = #ret
		if ngx.say then 
			ngx.say(ret);
		end
	end
end

--===================================ssdb function=====================================
--get data from ssdb, string to table
FOO.private_hash_get_table_ssdb = function( db_name_, key, hash , read_only)
	--[[
	local ssdb_dc_client = FOO.advert_ssdb_dc_client
	local ret = ssdb_dc_client:read( db_name_, key, hash, FOO.error_exit, nil, read_only )
	
	if  ret == ngx.null then
		log.debug( "get null value. ssdb_name=" .. db_name_ .. ", key=" .. key .. ", hash=" .. hash )
		return {}
	else
		if  #ret > 1024*100 then
			log.day_list("ssdb", "len", db_name_, key, hash, #ret )
		end
		local ret_table_ = table.loadstring( ret )
		if type(ret_table_) == 'table' then
			if not ssdb_dc_client:private_check_get_key( db_name_, key, hash, ret_table_ ) then
				log.day_list(ADVERT, "get", db_name_, key, hash, ret, debug.traceback() )
				ssdb_dc_client:clean_shared_cache_ssdb( db_name_, key, hash )
				FOO.error_exit("call hash_get_table_ssdb, [_k_] check fail." )
				return {}
			end
		else
			ssdb_dc_client:clean_shared_cache_ssdb( db_name_, key, hash )
			FOO.error_exit( "ssdb_error=" .. uu.to_str( ret ) .. ' ' .. key .. ' ' .. hash )
		end

		return ret_table_ or {}
	end
	--]]

	if tonumber(ngx.ctx.m_params.uin)==1000 then
		db_name_ = "comm"
	end
	local ssdb_ip = ns_config.advert_ssdb[db_name_].url
	local ssdb_port = ns_config.advert_ssdb[db_name_].port

	local db = ssdb:new()
	db:set_timeout(1000)
	local ok, err = db:connect(ssdb_ip, ssdb_port)
	if not ok then
		log.day_list("connect_ssdb", "failed to connect: ", err)
		return {}
	end
	ssdb.add_commands("auth")
	db:auth("xZtXkxJFyhHbfSbOXs6NflySwUHGCnLI")
	local results, err = db:hget(key, hash)
	if not results then
		log.day_list("connect_ssdb", "failed to hget requests: ", err)
		return {}
	end
	local ret_table_ = table.loadstring(results[1])
	return ret_table_ or {}
end

--table to string, write data to ssdb
--delay       :  1=不立即写ssdb    其他(默认值)=立即同时写ssdb
--read_only   :  1=不解开远程锁    其他(默认值)=如果有远程锁，立即解锁
-----             （可作为主动参数传入=1，暂时不用解锁，等待final解锁，适用于一次读取，多次写入的情况）
FOO.private_hash_set_table_ssdb = function(db_name_, key, hash, value, read_only, delay)
	--[[
	--其他(默认值)=如果有远程锁，立即解锁
	if not read_only  then
		read_only = 0 
	end
	--其他(默认值)=立即同时写ssdb [平台出过bug,所以默认值传nil就行。1为不立即写]
  	--if not delay  then
  		--delay = 0   
  	--end
	  
	local ssdb_response = "NONE"
	local ssdb_dc_client = FOO.advert_ssdb_dc_client
	if  value and type(value) == 'table' then
		if  ssdb_dc_client:private_check_set_key( db_name_, key, hash, value ) then
			local v = table.tostring( value )
			ssdb_response = ssdb_dc_client:save( db_name_, key, hash, v, FOO.error_exit, delay, read_only )
		else
			FOO.error_exit( "call hash_set_table_ssdb, [_k_] check fail." )
		end
	else
		FOO.error_exit( "call hash_set_table_ssdb, value is not a table." )
	end

	return ssdb_response
	--]]

	if tonumber(ngx.ctx.m_params.uin)==1000 then
		db_name_ = "comm"
	end
	local ssdb_ip = ns_config.advert_ssdb[db_name_].url
	local ssdb_port = ns_config.advert_ssdb[db_name_].port

	local db = ssdb:new()
	db:set_timeout(1000)
	local ok, err = db:connect(ssdb_ip, ssdb_port)
	if not ok then
		log.day_list("connect_ssdb", "failed to connect: ", err)
		return 
	end
	ssdb.add_commands("auth")
	db:auth("xZtXkxJFyhHbfSbOXs6NflySwUHGCnLI")
	local results, err = db:hset(key, hash, table.tostring(value))
	if not results then
		log.day_list("connect_ssdb", "failed to hset requests: ", err)
		return 
	end
	
	return "OK"
end

---增加一个读锁
FOO.private_hash_add_read_lock = function( db_name_, key, hash )
	local ssdb_dc_client = FOO.advert_ssdb_dc_client
	if  ssdb_dc_client then
		ssdb_dc_client:add_read_lock( db_name_, key, hash );
	end
end

--删除一个key
FOO.private_hash_del_key = function(db_name_, key, hash)
	local ssdb_dc_client = FOO.advert_ssdb_dc_client
	if  ssdb_dc_client then
		ssdb_dc_client:del(db_name_,key,hash,FOO.error_exit);
	end
end

return FOO